#! /usr/bin/python
# -*- coding:  utf-8 -*-
#
# accoufer : cgi script for creating/editing an offer
# 
# Copyright S.Keim 2011
# Available under the MIT licence see the COPYING file

import accoufer
import shelve
import cgi, os 
import math
import accerror

def run():
     # extract parameters
    form = cgi.FieldStorage()
    try:
        client = form["client"].value  # client service url
        oref = form["oref"].value  
        svalue = int(form["svalue"].value)  
        cvalue = int(form["cvalue"].value)  
        responder = form["responder"].value  
    except KeyError:
        return error(accerror.ERR_BAD_REQUEST, "missing parameter")
    except ValueError:
        return error(accerror.ERR_BAD_REQUEST, "invalid parameter")

    # get client reference
    clients = shelve.open(accoufer.CLIENT_PATH)
    try:
        clientref = clients[client][accoufer.CLT_REF]
        offers = shelve.open(accoufer.offerpath(clientref), 'w')
    except KeyError:
        return error(accerror.ERR_BAD_REQUEST, "unknown client")
  
    # check client
    err, txt = accoufer.authenticate(offers)
    if err:
        return error(err, txt)
    
    # get offer, initier and responder
    try:           
        o_ref, o_svalue, o_min_svalue, o_tx, o_login = offers[oref]
    except KeyError:     
        return error(accerror.ERR_UNKNOWN_OFFER, "unknown offer")
    
    users = shelve.open(accoufer.USER_PATH)
    initer = users[o_login]

    emails = shelve.open(accoufer.EMAIL_PATH)
    try:
        r_login = emails[responder]
    except KeyError:
        return error(accerror.ERR_USER, "unknown user")
    responder = users[r_login]
    
    if o_login == r_login:
        return error(accerror.ERR_PARAM, "Same initer and responder")
    
    # check input
    if svalue<o_min_svalue:
        return error(accerror.ERR_PARAM, 
                "Value must be greater than %s"%o_min_svalue)
    if svalue>o_svalue:
        return error(accerror.ERR_PARAM, 
                "Value must be lower than %s"%o_svalue)
    if svalue*o_tx>cvalue:
        return error(accerror.ERR_PARAM, "Rejected change rate")
  
    #offer > user credits should not be returned by the 'offers' message
    if svalue > initer[accoufer.USER_CREDITS]:
        return error(accerror.ERR_UNKNOWN_OFFER, "Unknown offer")  
        
    # do transaction
    imail, ipwd, icredit, ioffers = initer
    rmail, rpwd, rcredit, roffers = responder
    icredit -= svalue
    rcredit += svalue

    # remove offer if exausted
    o_svalue -= svalue
    if o_svalue>=o_min_svalue:
        offers[oref] = o_ref, o_svalue, o_min_svalue, o_tx, o_login 
    else:
        ioffers = [o for o in ioffers if o!=(clientref,oref)]
        del offers[oref]

    # save
    users[o_login] = imail, ipwd, icredit, ioffers
    users[r_login] = rmail, rpwd, rcredit, roffers 
    
    # log transaction
    accoufer.log(r_login, "Y", client, -cvalue, svalue, rcredit)
    accoufer.log(o_login, "N", client, cvalue, -svalue, icredit)
    
    print "Content-Type: text/plain"
    print
    print "OK"
    print "-"
    
def error(code, message):
    print "Content-Type: text/plain"
    print
    print "NOK"
    print code
    print message
    
if __name__=="__main__":
    run()
